#pragma once
#include <iostream> 
#include <sys/eventfd.h>  
#include <sys/epoll.h>
#include <functional>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <cassert>
#include <unistd.h>
#include <sys/timerfd.h>
#include <unordered_map>
#include <memory>
#include"Log.hpp"
#include <cstring>
// #include "../source/Poller.hpp"
// #include "../source/TimerWheel.hpp" 耦合解决相互包含问题
class EventLoop;
class TimerWheel; 
class Poller;
class Channel{
    private:
        int _fd;           //文件描述符,用于监控,
        EventLoop *_loop; //一个事件循环
        // Poller *_poller;  //一个事件监控 
        uint32_t _events; //当前监控的事件
        uint32_t _revents; //当前连接触发的事件

        using EventCallback = std::function<void()>;
        EventCallback _read_callback;  //可写事件回调
        EventCallback _write_callback; //可读
        EventCallback _error_callback;  //错误
        EventCallback _close_callback;  //连接断开
        EventCallback _event_callback;  //任意事件
    public:
        Channel(EventLoop* loop, int fd):_fd(fd),_events(0),_revents(0),_loop(loop){}
        int Fd() { return _fd; }    //获取文件描述符    
        uint32_t Events() { return _events; }  //获取监控的事件
        void SetREvents(uint32_t events) { _revents = events; }  //设置实际就绪的事件
        void SetReadCallback(const EventCallback &cb) { _read_callback = cb; }
        void SetWriteCallback(const EventCallback &cb) { _write_callback = cb; }
        void SetErrorCallback(const EventCallback &cb) { _error_callback = cb ;}
        void SetCloseCallback(const EventCallback &cb) { _close_callback = cb ; }
        void SetEventCallback(const EventCallback &cb) { _event_callback = cb ;}
        
        //判断监控事件
        bool ReadAble() { return (_events & EPOLLIN); }
        bool WriteAble() { return (_events & EPOLLOUT); }
        
        void EnableRead() { _events |= EPOLLIN; Updata(); }
        void EnableWrite() { _events |= EPOLLOUT; Updata(); }
        void DisableRead() { _events &= ~EPOLLIN; Updata(); } 
        void DisableWrite() { _events &= ~EPOLLOUT; Updata(); }
        void DisableAll() { _events = 0; Updata(); }
        //移除监控
        void Remove();
        void Updata();
        
        void HandleEvent(){
            //可读，对端关闭，紧急事件可读。
            if((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI)){
                if(_read_callback) _read_callback();
                //任何事件都会触发的事件
                if(_event_callback) _event_callback();
            }    
            if(_revents & EPOLLOUT){
                if(_write_callback) _write_callback();
                if(_event_callback) _event_callback();
            }else if(_revents & EPOLLERR){
                if(_event_callback) _event_callback();
                if(_error_callback) _error_callback();
            }else if(_revents & EPOLLHUP){
                if(_event_callback) _event_callback();
                if(_close_callback) _close_callback();
            }
        }
    };

#define MAX_EPOLLEVENTS 1024
class Poller{
private:
    int _epfd;      //用一个文件描述符_epfd管理文件,
    struct epoll_event _evs[MAX_EPOLLEVENTS]; //事件队列
    std::unordered_map<int,Channel *> _channels;
private:
    //对epoll的直接操作 
    void Updata(Channel *channel ,int op){
        int fd = channel->Fd();
        struct epoll_event ev;
        ev.data.fd = fd;
        ev.events = channel->Events();
        int ret = epoll_ctl(_epfd,op,fd,&ev); //系统调用
        if(ret<0){
            lg(Error,"EPOLLCTL FAILED!");//重复添加 ret<0
        }   
        return ;
    }
    //判断Channel是否添加了事件监控
    bool HashChannel(Channel *channel){
        auto it = _channels.find(channel->Fd());
        if(it == _channels.end()){
            return false;
        }
        return true;
    }
public:
    Poller(){
        _epfd = epoll_create(MAX_EPOLLEVENTS);  //系统调用创建epoll,MAX_EPOLLEVENTS只需要大于0,没有具体含义
        if(_epfd < 0){
            lg(Error,"EPOLL CREATE FAILED!!");
            abort(); //创建失败，退出
        }
    }
    //添加或修改监控事件
    void UpdataEvent(Channel *channel){
        bool ret = HashChannel(channel);
        if(ret == false){
            _channels.insert(std::make_pair(channel->Fd(),channel));
            return Updata(channel,EPOLL_CTL_ADD);
        }
        return Updata(channel,EPOLL_CTL_MOD);
    }
    //移除监控
    void RemoveEvent(Channel *channel){
        auto it = _channels.find(channel->Fd());
        if(it != _channels.end()){
            _channels.erase(it);
        }
        return Updata(channel,EPOLL_CTL_DEL);
    }
    //开始监控。
    void Poll(std::vector<Channel*> *active){
        int nfds = epoll_wait(_epfd,_evs,MAX_EPOLLEVENTS,-1);
        if(nfds < 0){
            if(errno == EINTR){ //EINTR：进程在
                //慢系统调用中阻塞，捕获到某个信号且相应的信号处理函
                //
                return;
            }
            lg(Error,"EPOLL WAIT ERROR:%s\n",strerror(errno));
            abort();
        }
        for(int i=0;i < nfds;i++){//所有就绪的事件
            auto it = _channels.find(_evs[i].data.fd);
            assert(it !=  _channels.end());
            it ->second ->SetREvents(_evs[i].events);//设置实际就绪的事件
            active->push_back(it->second);  //将就绪的事件放入active中
        }
        return;
    }    
};


using TaskFunc = std::function<void()>;
using ReleaseFunc = std::function<void()>;

class TimerTask{
private:
    uint64_t _id;       //定时器任务对象ID
    uint32_t _timeout;  //定时任务的超时时间
    bool _canceled;     //false-表示没有被取消， true-表示被取消
    TaskFunc _task_cb;  //定时器对象要执行的定时任务。
    ReleaseFunc _release; //拥有删除TimerWheel中保持的定时器对象信息
public:
    TimerTask(uint64_t id, uint32_t delay, const TaskFunc &cb):
    _id(id),_timeout(delay),_task_cb(cb),_canceled(false){
    }
    ~TimerTask(){
        if(_canceled == false) _task_cb();
        _release();
    }
    void Cancel() { _canceled = true; }
    void SetRelease( const ReleaseFunc &cb) { _release = cb; }
    uint32_t DelayTime() { return _timeout; }
};

class TimerWheel{
    private:
        using WeakTask = std::weak_ptr<TimerTask>;
        using PtrTask = std::shared_ptr<TimerTask>;
        int _tick; //当前的秒钟
        
        int _capacity; //表盘最⼤数量--其实就是最⼤延迟时间
        std::vector<std::vector<PtrTask>> _wheel; //时间轮or时间轴
        std::unordered_map<uint64_t,WeakTask> _timers;  //id和时间任务对象的映射
    
        EventLoop *_loop;
        int _timerfd; //定时器描述符——可读事件回调就是读取计数器，执行定时任务
        std::unique_ptr<Channel> _timer_channel;  //_timer_channel:定时器是事件
    private:
        void RemoveTimer(uint64_t id){
            auto it = _timers.find(id);
            if(it != _timers.end()){
                _timers.erase(it);
            }
        }
    
        static int CreateTimerfd(){
            int timerfd = timerfd_create(CLOCK_MONOTONIC,0); //创建
            if(timerfd < 0){
                lg(Error,"TIMERFD CREATE FAILED!");
                abort();
            }
            struct itimerspec itime;
            itime.it_value.tv_sec = 1;
            itime.it_value.tv_nsec = 0;//第一次超时事件为1s后
            itime.it_interval.tv_sec = 1;
            itime.it_interval.tv_nsec = 0;//
            timerfd_settime(timerfd,0,&itime,NULL);
            return timerfd;
        }
        int ReadTimefd(){
            uint64_t times;
            int ret = read(_timerfd, &times, 8);
            if(ret<0){
                lg(Error,"READ TIMEFD FAILED!");
                abort();
            }
            return times;
        }
        void RunTimerTask(){
            _tick = (_tick + 1)%_capacity;//
            _wheel[_tick].clear();
        }
        void OnTimer(){
            int times = ReadTimefd();//读取实际的超时次数
            for(int i=0;i<times;i++){
                RunTimerTask();
            }
        }
        void TimerAddInLoop(uint64_t id,uint32_t delay ,const TaskFunc& cb){
            PtrTask pt(new TimerTask(id,delay,cb));//创建定时任务
            pt->SetRelease(std::bind(&TimerWheel::RemoveTimer,this,id));//定时任务设置从wheel上erase的函数
            int pos = (_tick + delay) % _capacity;//时间轮挂载时间任务
            _wheel[pos].push_back(pt);
            _timers[id] = WeakTask(pt);
        }
        void TimerRefreshInLoop(uint64_t id){
            auto it = _timers.find(id);
            if(it == _timers.end()){
                return ; //没找到定时任务，没法刷新，没法延迟
            }
            PtrTask pt = it->second.lock();//
            int delay = pt->DelayTime();
            int pos = (delay+_tick) % _capacity;
            _wheel[pos].push_back(pt);
        }
        void TimerCancelInLoop(uint64_t id){
            auto it = _timers.find(id);
            if(it == _timers.end()){
                return ;
            }
            PtrTask pt = it->second.lock();
            if(pt) pt->Cancel();
        }
    public:
        TimerWheel(EventLoop *loop):_capacity(60), _tick(0),_wheel(_capacity),_loop(loop),
        _timerfd(CreateTimerfd()),_timer_channel(new Channel(_loop,_timerfd)){ //_timefd:
            _timer_channel -> SetReadCallback(std::bind(&TimerWheel::OnTimer,this));//
            _timer_channel -> EnableRead();      //启动时间监控
        }
        void TimerAdd(uint64_t id,uint32_t delay,const TaskFunc &cb);
        void TimerRefresh(uint64_t id);
        void TimerCancel(uint64_t id);
        bool HasTimer(uint64_t id){
            auto it = _timers.find(id);
            if( it == _timers.end()){
                return false;
            }
            return true;
        } 
    };

class EventLoop{
private:
    using Functor = std::function<void()>;
    std::thread::id _thread_id;//线程id
    int _event_fd;             
    std::unique_ptr<Channel> _event_channel;
    Poller _poller; //事件监控
    std::vector<Functor> _tasks;
    std::mutex _mutex;// 保证线程安全
    // TimerWheel _timer_wheel;//定时器模块
public:
    //执行线程池中所有的任务
    void RunAllTask(){
        std::vector<Functor> functor;
        {
            std::unique_lock<std::mutex> _lock(_mutex);
            _tasks.swap(functor);//拿到线程池中的任务
        }
        for(auto &f : functor){
            f();
        }
        return;
    }


    static int CreateEventFd(){
        int efd = eventfd(0,EFD_CLOEXEC|EFD_NONBLOCK);//返回一个创建的文件描述符 efd,
        if(efd<0){
            lg(Error,"CREATE EVENTFD FAILED!!");
            abort();
        }
        return efd;
    }

    void ReadEventfd(){
        uint64_t res = 0;
        int ret = read(_event_fd,&res,sizeof(res));//res表示_event_fd写入值之和
        if(ret<0){
            if(errno == EINTR || errno == EAGAIN){ //  EAGAIN -- 
                //表⽰⽆数据可读
                return;
            }
            lg(Error,"READ EVENTFD FAILED!");
            abort();
        }
        return;
    }

    void WeakUpEventFd(){
        uint64_t val = 1;
        int ret = write(_event_fd,&val,sizeof(val));
        if(ret<0){
            if(errno == EINTR){
                return;
            }
            lg(Error,"READ EVENTFD FAILED!");
            abort();
        }
        return ;
    }
public:
    EventLoop():_thread_id(std::this_thread::get_id()),
                _event_fd(CreateEventFd()),_event_channel(new Channel(this,_event_fd))
                /*,_timer_wheel(this)*/ {
        _event_channel->SetReadCallback(std::bind(&EventLoop::ReadEventfd,this));
        _event_channel->EnableRead();
    }
    
    void Start(){
        while(1){
            //1.事件监控
            std::vector<Channel *> actives;
            _poller.Poll(&actives);
            //2.事件处理
            for(auto &channel:actives){
                channel->HandleEvent();
            }
            //3.执行任务
            RunAllTask();
        }
    }

    bool IsInLoop(){
        return  _thread_id == std::this_thread::get_id();
    }
    
    void AssertInLoop(){
        assert( _thread_id == std::this_thread::get_id());
    }
    
    void RunInLoop(const Functor &cb){
        if(IsInLoop()){
            return cb();
        }
        return QueueInLoop(cb);
    }
    
    void QueueInLoop(const Functor &cb){
        {   
            std::unique_lock<std::mutex> _lock(_mutex);
            _tasks.push_back(cb);
        }
        //可能没有事件就绪，导致epoll阻塞
        //给eventfd写入一个数据，eventfd就会触发可读事件
        WeakUpEventFd();
    }
    
    void UpdataEvent(Channel *channel){
        return _poller.UpdataEvent(channel);
    }

    void RemoveEvent(Channel *channel){
        return _poller.RemoveEvent(channel);
    }

    // void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb){
    //     return _timer_wheel.TimerAdd(id,delay, cb);
    // }
    // void TimeRefresh(uint64_t id){
    //     return _timer_wheel.TimerRefresh(id);
    // }
    // void TimerCancel(uint64_t id){
    //     return _timer_wheel.TimerCancel(id);
    // }
    // bool HasTimer(uint64_t id){
    //     return _timer_wheel.HasTimer(id);
    // } 
};


class LoopThread{   //一个reactor线程对应一个事件循环
private:
    std::mutex _mutex; //互斥锁
    std::condition_variable _cond; //条件变量
    EventLoop *_loop;   //EventLoop指针变量，这个对象需要在线程内实例化
    std::thread _thread; //EventLoop对应的线程

private:
 /*实例化 EventLoop 对象，唤醒_cond上有可能阻塞的线程，并且开始运⾏EventLoop模块的功能*/
    void ThreadEntry(){
        EventLoop loop;
        {
            std::unique_lock<std::mutex> lock(_mutex);//加锁
            _loop = &loop;
            _cond.notify_all();
        }        
        loop.Start();
    }
public:
    //创建线程,
    LoopThread():_loop(NULL),
    _thread(std::thread(&LoopThread::ThreadEntry,this)){}
    
    EventLoop *GetLoop(){
        EventLoop *loop = NULL;
        {
            std::unique_lock<std::mutex> lock(_mutex); //加锁
            _cond.wait(lock,[&](){ return _loop !=NULL; });//1、条件不满足（_loop 为 NULL），自动解锁
            //。2、
            loop = _loop;
        }
        return loop;
    }
};

class LoopThreadPool{   
private:
    int _thread_count; //线程数量
    int _next_idx;      //下一个线程的索引
    EventLoop *_baseloop;   //主线程
    std::vector<LoopThread*> _threads; //线程池
    std::vector<EventLoop*> _loops;     //EventLoop对象
public:
    LoopThreadPool(EventLoop *baseloop):_thread_count(0),_next_idx(0)
            ,_baseloop(baseloop){}
    void SetThreadCount(int count) { _thread_count = count; }
    void Create(){
        if(_thread_count > 0 ){
            _threads.resize(_thread_count);
            _loops.resize(_thread_count);
            for(int i=0;i<=_thread_count;i++){
                _threads[i] = new LoopThread();
                _loops[i] = _threads[i]->GetLoop();
            }
        }
        return;
    }
    EventLoop *NextLoop(){
        if(_thread_count==0){ return _baseloop; }
        int _next_idx =( _next_idx + 1) % _thread_count;
        return _loops[_next_idx];
    }
};





void TimerWheel::TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb){
    _loop->RunInLoop(std::bind(&TimerWheel::TimerAddInLoop,this,id,delay,cb));
}
// 刷新/延迟定时任务
void TimerWheel::TimerRefresh(uint64_t id){
    _loop->RunInLoop(std::bind(&TimerWheel::TimerRefreshInLoop,this,id));
}
void TimerWheel::TimerCancel(uint64_t id){
    _loop->RunInLoop(std::bind(&TimerWheel::TimerCancelInLoop,this,id));
}

void Channel::Remove() {  _loop->RemoveEvent(this); } 
void Channel::Updata() {  _loop->UpdataEvent(this); }
    
    